﻿using System.Collections.Generic;

namespace Chess.Domain
{
    public class PieceFactory
    {
        private const int NumberPawns = 8;

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static List<Piece> CreateInitialPieces(Color color)
        {
            List<Piece> results = new List<Piece>();

            results.AddRange(CreatePawns(color));
            results.AddRange(CreateRooks(color));
            results.AddRange(CreateKnights(color));
            results.AddRange(CreateBishops(color));
            results.Add(CreateKing(color));
            results.Add(CreateQueen(color));

            return results;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <param name="type"></param>
        /// <param name="rank"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public static Piece CreatePiece(Color color, Type type, Position position)
        {
            Piece result = null;

            switch (type)
            {
                case Type.King:
                    result = new King();

                    break;
                case Type.Queen:
                    result = new Queen();

                    break;
                case Type.Bishop:
                    result = new Bishop();

                    break;
                case Type.Knight:
                    result = new Knight();

                    break;
                case Type.Rook:
                    result = new Rook();

                    break;
                case Type.Pawn:
                    result = new Pawn();

                    break;
            }

            result.Color = color;
            result.CurrentPosition = position;

            return result;
        }


        #region " Helper Methods "

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        internal static Piece CreateKing(Color color)
        {
            Piece result = null;
            Rank rank = DetermineRank(color);
            File file = File.E;

            result = CreatePiece(color, Type.King, new Position(rank, file));

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
		internal static Piece CreateQueen(Color color)
        {
            Piece result = null;
            Rank rank = DetermineRank(color);
            File file = File.D;

            result = CreatePiece(color, Type.Queen, new Position(rank, file));

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
		internal static List<Piece> CreateBishops(Color color)
        {
            List<Piece> results = new List<Piece>();
            Rank rank = DetermineRank(color);

            results.Add(CreatePiece(color, Type.Bishop, new Position(rank, File.C)));
            results.Add(CreatePiece(color, Type.Bishop, new Position(rank, File.F)));

            return results;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
		internal static List<Piece> CreateKnights(Color color)
        {
            List<Piece> results = new List<Piece>();
            Rank rank = DetermineRank(color);

            results.Add(CreatePiece(color, Type.Knight, new Position(rank, File.B)));
            results.Add(CreatePiece(color, Type.Knight, new Position(rank, File.G)));

            return results;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        internal static List<Piece> CreateRooks(Color color)
        {
            List<Piece> results = new List<Piece>();
            Rank rank = DetermineRank(color);

            results.Add(CreatePiece(color, Type.Rook, new Position(rank, File.A)));
            results.Add(CreatePiece(color, Type.Rook, new Position(rank, File.H)));

            return results;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        private static Rank DetermineRank(Color color)
        {
            Rank result;

            if (color == Color.White)
            {
                result = Rank.R1;
            }
            else
            {
                result = Rank.R8;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        internal static List<Piece> CreatePawns(Color color)
        {
            List<Piece> results = new List<Piece>();

            for (int index = 0; index < NumberPawns; index++)
            {
                Position position = new Position(DeterminePawnRank(color), DeterminPawnFile(index));

                results.Add(CreatePiece(color, Type.Pawn, position));
            }

            return results;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rank"></param>
        private static Rank DeterminePawnRank(Color color)
        {
            Rank result;

            if (color == Color.White)
            {
                result = Rank.R2;
            }
            else
            {
                result = Rank.R7;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        private static File DeterminPawnFile(int index)
        {
            File result;

            result = (File)index;

            return result;
        }

        #endregion
    }
}
